#include "onedayleftsecondstest.h"
#include <stdexcept>

void OneDayLeftSecondsTest::initTestCase()
{
    qDebug() << "=== 初始化 OneDayLeftSeconds 测试用例 ===";

    // 初始化路径
    testDataFileBase = getTestDataBasePath();
    testResultFileBase = getTestResultBasePath();

    qDebug() << "测试数据基础路径:" << testDataFileBase;
    qDebug() << "测试结果基础路径:" << testResultFileBase;

    // 验证路径
    QDir testDataDir(testDataFileBase);
    if (!testDataDir.exists()) {
        qFatal("❌ 测试数据目录不存在: %s", testDataFileBase.toUtf8().constData());
    }

    QDir testResultDir(testResultFileBase);
    if (!testResultDir.exists()) {
        qDebug() << "创建测试结果目录...";
        if (testResultDir.mkpath(".")) {
            qDebug() << "✅ 测试结果目录创建成功";
        } else {
            qWarning() << "❌ 测试结果目录创建失败";
        }
    }

    qDebug() << "✅ OneDayLeftSeconds 测试环境初始化完成";
}

QString OneDayLeftSecondsTest::getTestDataBasePath()
{
    QDir currentDir(QDir::currentPath());

    // 从构建目录回退5级到 algorithm-test 目录
    QDir targetDir = currentDir.filePath("../../../../../test_data");
    QString absolutePath = targetDir.absolutePath() + "/";

    if (targetDir.exists()) {
        qDebug() << "✅ 使用相对路径找到测试数据:" << absolutePath;
        return absolutePath;
    } else {
        qWarning() << "❌ 相对路径找不到测试数据，使用硬编码路径";
        return "D:/Work/algorithm-test/test_data/";
    }
}

QString OneDayLeftSecondsTest::getTestResultBasePath()
{
    QDir currentDir(QDir::currentPath());

    // 从构建目录回退5级到 algorithm-test 目录
    QDir targetDir = currentDir.filePath("../../../../../test_result");
    QString absolutePath = targetDir.absolutePath() + "/";

    if (targetDir.exists()) {
        qDebug() << "✅ 使用相对路径找到测试结果路径:" << absolutePath;
        return absolutePath;
    } else {
        // 尝试创建目录
        if (targetDir.mkpath(".")) {
            qDebug() << "✅ 创建测试结果路径:" << absolutePath;
            return absolutePath;
        } else {
            qWarning() << "❌ 无法创建测试结果路径，使用硬编码路径";
            return "D:/Work/algorithm-test/test_result/";
        }
    }
}

void OneDayLeftSecondsTest::cleanupTestCase()
{
    qDebug() << "清理 OneDayLeftSeconds 测试用例...";
}

QJsonObject OneDayLeftSecondsTest::readJsonObject(const QString& filePath)
{
    qDebug() << "读取JSON对象文件:" << filePath;

    QFileInfo fileInfo(filePath);
    qDebug() << "文件绝对路径:" << fileInfo.absoluteFilePath();
    qDebug() << "文件是否存在:" << fileInfo.exists();

    QFile file(filePath);
    if (!file.open(QIODevice::ReadOnly)) {
        QString errorMsg = QString("无法打开文件：%1").arg(filePath);
        qWarning() << errorMsg;
        throw std::runtime_error(errorMsg.toStdString());
    }

    QByteArray data = file.readAll();
    file.close();

    qDebug() << "文件大小:" << data.size() << "字节";

    QJsonDocument doc = QJsonDocument::fromJson(data);
    if (doc.isNull()) {
        qWarning() << "JSON解析失败，文件内容:" << QString(data).left(100) << "...";
        throw std::runtime_error("JSON解析失败");
    }

    qDebug() << "JSON对象解析成功，键数量:" << doc.object().keys().size();
    return doc.object();
}

void OneDayLeftSecondsTest::createFileRecursion(const QString& fileName)
{
    qDebug() << "创建文件:" << fileName;

    QFileInfo fileInfo(fileName);
    QDir dir = fileInfo.absoluteDir();

    qDebug() << "目标目录:" << dir.absolutePath();
    qDebug() << "目录是否存在:" << dir.exists();

    if (!dir.exists()) {
        qDebug() << "创建目录...";
        if (dir.mkpath(".")) {
            qDebug() << "目录创建成功";
        } else {
            qWarning() << "目录创建失败";
        }
    }

    QFile file(fileName);
    if (!file.exists()) {
        if (file.open(QIODevice::WriteOnly)) {
            qDebug() << "文件创建成功";
            file.close();
        } else {
            qWarning() << "文件创建失败";
        }
    } else {
        qDebug() << "文件已存在";
    }
}

void OneDayLeftSecondsTest::clearOneDayLeftSecondsResultFolder()
{
    QString resultFolderPath = testResultFileBase + "oneDayLeftSeconds_c/";
    QDir resultFolder(resultFolderPath);

    if (resultFolder.exists()) {
        QStringList files = resultFolder.entryList(QDir::Files);
        for (const QString& file : files) {
            if (!resultFolder.remove(file)) {
                qWarning() << "无法删除文件:" << file;
            }
        }
        qDebug() << "已清空结果文件夹:" << resultFolderPath;
    } else {
        qDebug() << "结果文件夹不存在，无需清空:" << resultFolderPath;
    }
}

void OneDayLeftSecondsTest::testOneDayLeftSeconds()
{
    qDebug() << "=== 开始测试 OneDayLeftSeconds 方法 ===";
    qDebug() << "测试数据基础路径:" << testDataFileBase;
    qDebug() << "测试结果基础路径:" << testResultFileBase;

    // 清空结果文件夹
    clearOneDayLeftSecondsResultFolder();

    // 测试随机用例 (1-50) 和手动用例 (1-2)
    for (int i = 1; i <= 52; i++) {
        try {
            QString folderPath;
            QString resultFileName;

            if (i <= 50) {
                folderPath = testDataFileBase + QString("oneDayLeftSeconds/random_case_%1/").arg(i);
                resultFileName = testResultFileBase + QString("oneDayLeftSeconds_c/random_case_%1.txt").arg(i);
            } else {
                folderPath = testDataFileBase + QString("oneDayLeftSeconds/manual_case_%1/").arg(i - 50);
                resultFileName = testResultFileBase + QString("oneDayLeftSeconds_c/manual_case_%1.txt").arg(i - 50);
            }

            QDir folder(folderPath);

            // 检查文件夹是否存在
            if (!folder.exists()) {
                qWarning() << "文件夹不存在：" << folderPath;
                continue;
            }

            qDebug() << "\n=== 处理测试用例" << (i <= 50 ? "random_case_" : "manual_case_") << (i <= 50 ? i : (i - 50)) << "===";
            qDebug() << "数据文件夹:" << folderPath;

            // 加载测试数据
            QString testCasesPath = folderPath + "test_cases.json";
            qDebug() << "测试用例文件路径:" << testCasesPath;

            QFile testCasesFile(testCasesPath);
            if (!testCasesFile.open(QIODevice::ReadOnly)) {
                qWarning() << "无法打开测试用例文件：" << testCasesPath;
                continue;
            }

            QByteArray testDataBytes = testCasesFile.readAll();
            testCasesFile.close();

            QJsonDocument testDataDoc = QJsonDocument::fromJson(testDataBytes);
            if (testDataDoc.isNull()) {
                qWarning() << "测试用例JSON解析失败";
                continue;
            }

            QJsonObject testData = testDataDoc.object();

            // 解析工作时间数据
            QJsonArray workTimeArray = testData["rVecWorkTimeDto"].toArray();
            QVector<CWorkTime> workTimes;

            qDebug() << "=== 工作时间段数据 ===";
            qDebug() << "工作时间段数量:" << workTimeArray.size();

            for (int j = 0; j < workTimeArray.size(); ++j) {
                QJsonValue value = workTimeArray[j];
                if (!value.isObject()) {
                    qWarning() << "工作时间段" << j << "不是有效的对象";
                    continue;
                }

                QJsonObject workTimeObj = value.toObject();

                QString startTimeStr = workTimeObj["mWorkStartTime"].toString();
                QString endTimeStr = workTimeObj["mWorkEndTime"].toString();

                qDebug() << "工作时间段" << j << "原始字符串 - 开始:" << startTimeStr << "结束:" << endTimeStr;

                QTime startTime = QTime::fromString(startTimeStr, "hh:mm:ss");
                QTime endTime = QTime::fromString(endTimeStr, "hh:mm:ss");

                qDebug() << "工作时间段" << j << "解析后 - 开始:" << startTime.toString("hh:mm:ss")
                         << "结束:" << endTime.toString("hh:mm:ss")
                         << "有效性 - 开始:" << startTime.isValid() << "结束:" << endTime.isValid();

                if (!startTime.isValid() || !endTime.isValid()) {
                    qWarning() << "工作时间段" << j << "时间解析失败!";
                    continue;
                }

                CWorkTime workTime;
                workTime.update(startTime, endTime);
                workTimes.append(workTime);
            }

            // 解析开始和结束时间
            QString startTimeStr = testData["rStartTime"].toString();
            QString endTimeStr = testData["rEndTime"].toString();

            qDebug() << "=== 时间范围数据 ===";
            qDebug() << "开始时间原始字符串:" << startTimeStr;
            qDebug() << "结束时间原始字符串:" << endTimeStr;

            QTime startTime = QTime::fromString(startTimeStr, "hh:mm:ss");
            QTime endTime = QTime::fromString(endTimeStr, "hh:mm:ss");

            qDebug() << "开始时间解析后:" << startTime.toString("hh:mm:ss") << "有效性:" << startTime.isValid();
            qDebug() << "结束时间解析后:" << endTime.toString("hh:mm:ss") << "有效性:" << endTime.isValid();

            if (!startTime.isValid() || !endTime.isValid()) {
                qWarning() << "开始或结束时间解析失败!";
                continue;
            }

            // 输出所有测试数据的汇总
            qDebug() << "=== 测试数据汇总 ===";
            qDebug() << "工作时间段总数:" << workTimes.size();
            for (int j = 0; j < workTimes.size(); ++j) {
                const CWorkTime& wt = workTimes[j];
                qDebug() << "时间段" << j << ":" << wt.mWorkStartTime.toString("hh:mm:ss") << "-" << wt.mWorkEndTime.toString("hh:mm:ss");
            }
            qDebug() << "查询时间范围:" << startTime.toString("hh:mm:ss") << "-" << endTime.toString("hh:mm:ss");

            // 创建服务实例并执行测试
            CHolidaySet service;
            int result = service.OneDayLeftSeconds(workTimes, startTime, endTime);

            // 写入测试结果
            createFileRecursion(resultFileName);

            QFile resultFile(resultFileName);
            if (!resultFile.open(QIODevice::WriteOnly | QIODevice::Text)) {
                qWarning() << "无法创建结果文件：" << resultFileName;
                continue;
            }

            QTextStream resultStream(&resultFile);
            resultStream << result;
            resultFile.close();

            qDebug() << "=== 计算结果 ===";
            qDebug() << "结果:" << result << "秒 (" << (result / 3600.0) << "小时)";
            qDebug() << "结果文件:" << resultFileName;

        } catch (const std::exception& e) {
            qWarning() << "测试失败:" << (i <= 50 ? "random_case_" : "manual_case_") << (i <= 50 ? i : (i - 50)) << "错误:" << e.what();
        }
    }
}
